#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
#define DELIM " \t"
#define LINE_SIZE 1024
#define ARGV_SIZE 32
#define EXIT_CODE 44


int quit = 0;
char commandline[LINE_SIZE];
char* argv[ARGV_SIZE] = {NULL};
extern char** environ;
int lastcode = 0;
char pwd[LINE_SIZE];
char myenv[LINE_SIZE];

const char* getusername()
{
  return getenv("USER");
}

const char* gethostname()
{
  return getenv("HOSTNAME");
}

const char* getpwd()
{
  return getcwd(pwd,sizeof(pwd));
}

void Interact(char* cline, int size)
{
  getpwd();
  printf(LEFT"%s@%s %s"RIGHT""LABLE" ",getusername(),gethostname(),pwd);
  char* s = fgets(cline,size,stdin);
  assert(s);
  (void)s;
  // "abcd\n\0" 去除这个"\n"
  cline[strlen(cline)-1] = '\0';
}

int splitstring(char* cline, char* _argv[])
{
  int i = 0;
  _argv[i++] = strtok(cline,DELIM);
  while(_argv[i++] = strtok(NULL,DELIM)) {};
  return i - 1;
}

void NormalExcute(char* _argv[])
{
  pid_t id = fork();
  if (id < 0) {
    perror("fork");
    return;
  }
  else if (id == 0) {
    //execvpe(_argv[0],_argv,environ);
    execvp(_argv[0],_argv);
    exit(EXIT_CODE);
  }
  else {
    int status = 0;
    pid_t rid = waitpid(id, &status, 0);
    if (rid == id) {
      lastcode = WEXITSTATUS(status);
    }
  }
}

int buildCommand(char* _argv[], int _argc)
{

    if (_argc == 2 && strcmp(_argv[0],"cd") == 0) {
      chdir(_argv[1]);
      getpwd();
      sprintf(getenv("PWD"),"%s",pwd);
      return 1;
    }
    else if (_argc == 2 && strcmp(_argv[0], "export") == 0) {
      strcpy(myenv, _argv[1]);
      putenv(myenv);
      return 1;
    }
    else if (_argc == 2 && strcmp(_argv[0], "echo") == 0) {
      if (strcmp(_argv[1], "$?") == 0) {
        printf("%d\n", lastcode);
      }
      else if (*_argv[1] == '$') {
        char *val = getenv(_argv[1]+1);
        if (val) printf("%s\n", val);
      }
      else {
        printf("%s\n",_argv[1]);
      }
      return 1;
    }

    // 特殊处理ls
    if (strcmp(_argv[0], "ls") == 0) {
      _argv[_argc++] = "--color";
      _argv[_argc] = NULL;
      return 0;
    } 

}

int main()
{
  while (!quit) {
    // 1.
    // 2.交互问题,获取命令行，ls -a -l > myfile / ls -a -l >> myfile / cat file.txt
    Interact(commandline, LINE_SIZE);
    // printf("echo: %s\n",commandline);
   
    // 3. 子串分割问题，解析命令行
    // ls -a -l > "ls" 和"-a" 和"-l"
    int argc = splitstring(commandline,argv);
    if (argc == 0) continue; 
    //debug
   // for(int i = 0; i < argc; ++i) {
   //   printf("[%d] : %s\n",i,argv[i]);
   // }
   
   // 4. 指令的判断
    int n = buildCommand(argv, argc);

  //  5. 普通命令的执行
    if (!n) NormalExcute(argv);
  }
  return 0;
}
